package com.yumingjiang.common.util;

import org.w3c.dom.*;
import org.xml.sax.InputSource;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

public class XmlUtils {
    private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    private static final XPathFactory xPathFactory = XPathFactory.newInstance();
    
    // 私有构造函数防止实例化
    private XmlUtils() {}

    /**
     * 解析XML字符串为Document对象
     * @param xmlString XML字符串
     * @return 解析后的Document对象
     * @throws RuntimeException 解析失败时抛出
     */
    public static Document parseXml(String xmlString) {
        try {
            DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
            return builder.parse(new InputSource(new StringReader(xmlString)));
        } catch (Exception e) {
            throw new RuntimeException("XML解析失败", e);
        }
    }

    /**
     * 将Document对象转换为格式化的XML字符串
     * @param doc Document对象
     * @return 格式化后的XML字符串
     */
    public static String convertToString(Document doc) {
        try {
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
            return writer.toString();
        } catch (TransformerException e) {
            throw new RuntimeException("XML转换失败", e);
        }
    }

    /**
     * 创建新的XML文档
     * @return 新Document对象
     */
    public static Document createNewDocument() {
        try {
            return documentBuilderFactory.newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("文档创建失败", e);
        }
    }

    /**
     * XPath查询
     * @param doc Document对象
     * @param xpathExpression XPath表达式
     * @return 查询结果字符串
     */
    public static String evaluateXpath(Document doc, String xpathExpression) {
        try {
            XPath xpath = xPathFactory.newXPath();
            XPathExpression expr = xpath.compile(xpathExpression);
            return expr.evaluate(doc);
        } catch (XPathExpressionException e) {
            throw new RuntimeException("XPath查询失败", e);
        }
    }

    /**
     * 创建XML元素并设置文本内容
     * @param doc Document对象
     * @param tagName 元素名称
     * @param textContent 文本内容
     * @return 创建的Element
     */
    public static Element createElement(Document doc, String tagName, String textContent) {
        Element element = doc.createElement(tagName);
        element.setTextContent(textContent);
        return element;
    }

    /**
     * 为元素添加属性
     * @param element 目标元素
     * @param attributes 属性键值对
     */
    public static void addAttributes(Element element, Map<String, String> attributes) {
        for (Map.Entry<String, String> entry : attributes.entrySet()) {
            element.setAttribute(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 创建并附加子元素
     * @param parent 父元素
     * @param tagName 子元素名称
     * @param textContent 文本内容
     * @return 创建的子元素
     */
    public static Element appendChildElement(Element parent, String tagName, String textContent) {
        Element child = parent.getOwnerDocument().createElement(tagName);
        child.setTextContent(textContent);
        parent.appendChild(child);
        return child;
    }
}